//
//  CantripWorldDocument.m
//  Cantrip
//
//  Created by James Callender on Wed Apr 24 2002.
//  Copyright (c) 2001 James Callender. All rights reserved.
//

#import "CantripWorldDocument.h"

NSString *WorldVersionString;
NSString *WorldVersionKey;
NSString *WorldDataKey;

NSString *WorldDataAddressKey;
NSString *WorldDataPortKey;
NSString *WorldConnectOnOpenKey;
NSString *WorldDataEchoKey;
NSString *WorldReturnStyleKey;
NSString *WorldClearInputKey;
NSString *WorldEnableMCCP;

NSString *WorldSmartScrollingKey;
NSString *WorldSpellCheckingKey;
NSString *WorldSmartInsertDeleteKey;

NSString *WorldFontNameKey;
NSString *WorldFontSizeKey;
NSString *WorldTabSizeKey;
NSString *WorldScrollbackKey;
NSString *WorldDisplayRowsKey;
NSString *WorldDisplayColsKey;
NSString *WorldEchoColor;
NSString *WorldMessagesColor;
NSString *WorldDisplayForegroundColorKey;
NSString *WorldDisplayBackgroundColorKey;
NSString *WorldBoldIntenseColorsKey;
NSString *WorldEnableIntenseColorsKey;
NSString *WorldEnableANSIColorsKey;
NSString *WorldEnableTextBlinkingKey;
NSString *WorldStandardANSIColorsKey;
NSString *WorldIntenseANSIColorsKey;
NSString *WorldInputBackgroundColorKey;
NSString *WorldInputForegroundColorKey;
NSString *WorldInputFontNameKey;
NSString *WorldInputFontSizeKey;

// Telnet options

NSString *WorldHandleNAWSKey;
NSString *WorldPasswordPromptKey;
NSString *WorldHandleEraseCharacterKey;
NSString *WorldHandleEraseLineKey;
NSString *WorldHandleStatusPromptKey;
NSString *WorldClientTypeKey;

@implementation CantripWorldDocument

+ (void)initialize
{
    WorldVersionString  = @"2.1";
    WorldVersionKey     = @"Version";
    WorldDataKey	= @"WorldData";
    
    WorldDataAddressKey     = @"worldAddress";
    WorldDataPortKey	    = @"worldPort";
    WorldConnectOnOpenKey   = @"connectOnOpen";
    WorldDataEchoKey	    = @"echoStyle";
    WorldReturnStyleKey     = @"returnStyle";
    WorldEnableMCCP	    = @"enableMCCP";
    
    WorldClearInputKey      = @"enableClearInput";
    
    WorldSmartScrollingKey   = @"enableSmartScrolling";
    WorldSpellCheckingKey    = @"enableSpellChecking";
    WorldSmartInsertDeleteKey= @"enableSmartInsertDelete";
    
    WorldFontNameKey    = @"fontName";
    WorldFontSizeKey    = @"fontSize";
    WorldTabSizeKey     = @"tabSize";
    WorldScrollbackKey  = @"scrollback";
    WorldDisplayRowsKey	= @"displayRows";
    WorldDisplayColsKey	= @"displayColumns";
    WorldEchoColor      = @"echoColor";
    WorldMessagesColor  = @"messagesColor";
    WorldDisplayForegroundColorKey  = @"displayForegroundColor";
    WorldDisplayBackgroundColorKey  = @"displayBackgroundColor";
    WorldBoldIntenseColorsKey       = @"emboldenIntenseColors";
    WorldEnableIntenseColorsKey     = @"enableIntenseColors";
    WorldEnableANSIColorsKey	    = @"enableANSIColors";
    WorldEnableTextBlinkingKey	    = @"enableTextBlinking";
    WorldStandardANSIColorsKey      = @"standardANSIColors";
    WorldIntenseANSIColorsKey       = @"intenseANSIColors";
    WorldInputBackgroundColorKey    = @"inputBackgroundColor";
    WorldInputForegroundColorKey    = @"inputForegroundColor";
    WorldInputFontNameKey	    = @"inputFontName";
    WorldInputFontSizeKey	    = @"inputFontSize";
    
    WorldHandleNAWSKey = @"handleNAWS";
    WorldPasswordPromptKey = @"promptForPassword";
    WorldHandleEraseCharacterKey = @"handleEraseCharacter";
    WorldHandleEraseLineKey = @"handleEraseLine";
    WorldHandleStatusPromptKey = @"handleStatusPrompt";
    WorldClientTypeKey = @"clientType";
}

- (id)init
{
    if (self = [super init])
    {
		mWorldData = [[NSMutableDictionary alloc] init];
		mWorldWindows = [[NSMutableArray alloc] init];
		[[self undoManager] setLevelsOfUndo:10]; // Make it customizable?
		_loadFileName = nil;
		counter = 1;
    }
    return self;
}

- (void)makeWindowControllers
{
    CantripWorldController *controller;
	
    controller = [[CantripWorldController alloc] initWithWindowNibName:@"CantripWorldDocument"];
    //[controller setShouldCloseDocument:NO];
    [self addWindowController:controller];
    [mWorldWindows addObject:[controller window]];
    
    if (_loadFileName != nil) {
		[self loadFromFile:_loadFileName];
    }
    
    [controller loadPreferences];
    [[controller window] makeKeyAndOrderFront:self];
    [controller controllerWasInitialized];
    
    [[CantripPluginManager sharedPluginManager]
            makePluginsPerformSelector:@selector(windowControllerDidInitialize:) withObject:controller];
    
    [controller release];
}

- (void)dealloc
{
    [mWorldData release];
    [mWorldWindows release];
    [super dealloc];
}

+ (CantripWorldDocument *)activeWorld
{
    return [[CantripWorldController sharedDocumentController] activeDocument];
}


- (void)close
{
    [[CantripPluginManager sharedPluginManager]
        makePluginsPerformSelector:@selector(applicationWillCloseWorld:) withObject:self];
    [super close];
    //NSLog(@"%@", [self windowControllers]); 
    [[CantripWorldSettingsController sharedInstance] updateAllForClose:self];
}

/*
 - (void)document:(NSDocument *)doc shouldClose:(BOOL)shouldClose contextInfo:(void *)contextInfo
 {
	 int pluginIndex;
	 
	 if (!shouldClose) return;
	 
	 
	 for (pluginIndex = 0; pluginIndex < [[[PluginsManager sharedPluginsManager] pluginsArray] count]; pluginIndex++)
	 {
		 CantripPlugin *plugin = [[[PluginsManager sharedPluginsManager] pluginsArray] objectAtIndex:pluginIndex];
		 NSLog(@"Message sent\n");
		 [plugin applicationWillCloseWorld:self];
	 }
	 
 }*/

- (NSMutableDictionary *)worldData
{
    return mWorldData;
}

- (NSMutableDictionary *)data
{
    return mWorldData;
}

- (id)valueForKeyPath:(NSString *)keyPath
{
    if ([keyPath hasPrefix:@"data."]) { 
		return [mWorldData valueForKeyPath:[keyPath substringFromIndex:5]]; 
    } else if ([keyPath isEqualToString:@"data"]) {
		return mWorldData;
    }
    else return nil;
}

- (BOOL)validateData:(id *)ioValue error:(NSError **)outError
{
    return YES;
}

- (id)valueForUndefinedKey:(NSString *)key
{
    return nil;
}

- (void)undoValue:(id)object forKeyPath:(NSString *)path
{
    BOOL doUndo = YES;
    
    if ([self isDocumentEdited] == NO && [[self undoManager] isUndoing]) {
		doUndo = (NSRunAlertPanel(@"Warning", @"You are about to undo past the last point this document was saved.  Are you sure you want to undo?", @"Undo", @"Don't Undo", nil) == NSOKButton);
    }
    
    if (doUndo) {	
		[[[self undoManager] prepareWithInvocationTarget:self] undoValue:[self valueForKeyPath:path] forKeyPath:path];
		
		[mWorldData willChangeValueForKey:[path substringFromIndex:5]];
		[mWorldData setValue:object forKeyPath:[path substringFromIndex:5]]; 
		[mWorldData didChangeValueForKey:[path substringFromIndex:5]];
		
		if ([[self undoManager] isUndoing]) [self updateChangeCount:NSChangeUndone];
		else if ([[self undoManager] isRedoing]) [self updateChangeCount:NSChangeDone];
		[[self windowControllers] makeObjectsPerformSelector:@selector(loadPreferences)];
    }
}

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath
{
    if ([keyPath hasPrefix:@"data."]) { 
		[[[self undoManager] prepareWithInvocationTarget:self] undoValue:[self valueForKeyPath:keyPath] forKeyPath:keyPath];
		
		[mWorldData willChangeValueForKey:[keyPath substringFromIndex:5]];
		[mWorldData setValue:value forKeyPath:[keyPath substringFromIndex:5]]; 
		[mWorldData didChangeValueForKey:[keyPath substringFromIndex:5]];
		
		[self updateChangeCount:NSChangeDone];
		[[self windowControllers] makeObjectsPerformSelector:@selector(loadPreferences)];
    }
}

- (void)setData:(id)value forKeyPath:(NSString *)keyPath
{
    [self setValue:value forKeyPath:[@"data." stringByAppendingString:keyPath]];
}

- (int)incrementChild
{
    return counter++;
}

- (void)timerBeat:(id)sender
{
    NSEnumerator *e;
    CantripWorldWindow *c;
    
    if ([[mWorldData objectForKey:@"DisableTextBlinking"] boolValue]) return;
    
    e = [mWorldWindows objectEnumerator];
    while (c = [e nextObject]) {
		[[c windowController] timerBeat:sender];
    }
}

- (IBAction)newWorldWindowAction:(id)sender
{
    CantripWorldController *controller = [[CantripWorldController alloc] initWithWindowNibName:@"CantripWorldDocument"];
	
    [self addWindowController:controller];
    [mWorldWindows addObject:[controller window]];
    [controller loadPreferences];
    [[controller window] makeKeyAndOrderFront:self];
    [controller controllerWasInitialized];
    
    [[CantripPluginManager sharedPluginManager]
	makePluginsPerformSelector:@selector(windowControllerDidInitialize:) withObject:controller];
    
    [controller release];
}

- (void)updateVisualSettings:(id)sender
{
    unsigned int i;
    for (i = 0; i < [mWorldWindows count]; i++) {
		CantripWorldController *controller = [[mWorldWindows objectAtIndex:i] windowController];
		[controller loadPreferences];
    }
}

- (void)loadFromFile:(NSString *)fileName
{
    NSDictionary *fileDict = [NSUnarchiver unarchiveObjectWithFile:fileName];
	//    NSDictionary *fileDict = [NSDictionary dictionaryWithContentsOfFile:fileName];
    [[mWorldWindows objectAtIndex:0] setFrame:[[fileDict objectForKey:@"Rect"] rectValue] display:YES];
    [mWorldData setDictionary:[fileDict objectForKey:WorldDataKey]];
	
}

- (BOOL)readFromFile:(NSString *)fileName ofType:(NSString *)docType
{
    NSDictionary *data = [NSUnarchiver unarchiveObjectWithFile:fileName];
    //NSDictionary *data = [NSDictionary dictionaryWithContentsOfFile:fileName];
    if (![[data objectForKey:WorldVersionKey] isEqual:WorldVersionString]){
		int response = NSRunAlertPanel(@"Caution", @"This world file was saved in an older format.  Attempt to open anyways?",
									   @"Okay", @"Cancel", nil);
		if (response == NSAlertAlternateReturn)
			return NO;
    }
    
    if ([mWorldWindows count] > 0) {
		[self loadFromFile:fileName];
    } else {
        _loadFileName = fileName;
    }
	
    return YES;
}


- (BOOL)writeToFile:(NSString *)fileName ofType:(NSString *)type
{
    NSDictionary *data;
	
    [[CantripPluginManager sharedPluginManager]
	makePluginsPerformSelector:@selector(applicationWillSaveWorld:) withObject:self];
	
    data = [NSDictionary dictionaryWithObjectsAndKeys:
		WorldVersionString, WorldVersionKey,
		mWorldData, WorldDataKey,
		[NSValue valueWithRect:[[mWorldWindows objectAtIndex:0] frame]], @"Rect",
		nil];
	
    return [NSArchiver archiveRootObject:data toFile:fileName];
    //return [data writeToFile:fileName atomically:YES];
}

@end
